/*
 * Copyright 2014-2026 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.wzq.util;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.text.DecimalFormat;
import java.util.Properties;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;


/**
 */
public class UtilIo {
	protected static final Logger logger = LogManager.getLogger();
	public static final Charset utf8 = Charset.forName("UTF-8"), iso8859_1 = Charset.forName("ISO8859-1"), gbk = Charset.forName("GBK");
	
	private static final long KB = 1024, MB = 1024 * KB;
	public static final long GB = 1024 * MB;
	private static final long TB = 1024 * GB;
	private static final long PB = 1024 * TB;
	private static final long ZB = 1024 * PB;
	public static String prettyByte(Number sizeOfByte) {
		if (sizeOfByte == null) return null;
		
		long size = sizeOfByte.longValue();
		if (size == 0) return "0 KB";
		if (size < KB) return sizeOfByte + " B";
		
		DecimalFormat format = new DecimalFormat("#.##");
		if (size < MB) return format.format(1.0 * size / KB) + "KB";
		if (size < GB) return format.format(1.0 * size / MB) + "MB";
		if (size < TB) return format.format(1.0 * size / GB) + "GB";
		if (size < PB) return format.format(1.0 * size / TB) + "TB";
		if (size < ZB) return format.format(1.0 * size / PB) + "PB";
		return format.format(1.0 * size / ZB) + "ZB";
	}
	
	public static void close(AutoCloseable... closeables) {
		for (AutoCloseable closeable : closeables) {
			if (closeable != null) {
				try {
					closeable.close();
				} catch (Exception e) {
					logger.info("忽略异常 {}", closeable, e);
				}
			}
		}
	}
	
	/**
	 * 读取流为字节
	 * @param in 输入流，本函数不负责关闭
	 * @param size 预计大小 (如果&lt;8192使用8192)
	 */
	public static ByteArrayOutputStream read(InputStream in, Integer size) throws IOException {
		try (ByteArrayOutputStream out = new ByteArrayOutputStream(size == null || size < 8192 ? 8192 : size)) {
			byte[] buf = new byte[8192];
			for (int len; (len = in.read(buf)) != -1;) {
				out.write(buf, 0, len);
			}
			return out;
		}
	}
	
	/**
	 * 读取为字符串
	 * @param name 默认按资源读取，如果不存在按文件读取
	 */
	public static ByteArrayOutputStream readText(String name) throws IOException {
		InputStream in = null;
		try {
			in = UtilObj.getClassLoader().getResourceAsStream(name.charAt(0) == '/' ? name.substring(1) : name);
			if (in == null) {
				File file = new File(name);
				logger.info("无法按ClassLoader.getResourceAsStream读取，尝试按磁盘文件方式读取：{}", file);
				in = new FileInputStream(file);
			}
			return read(in, null);
		} finally {
			close(in);
		}
	}
	public static InputStream getResourceAsStream(String name) {
		if (name == null || name.isEmpty()) return null;
		
		InputStream in = null;  
		if(name.charAt(0) == '/') in = getResourceAsStream(name.substring(1));
		
		if (in == null) in = UtilObj.getClassLoader().getResourceAsStream(name);
		
		if (in == null) {
			File file = new File(name);
			if (file.exists()) {
				try {
					in = new FileInputStream(new File(name));
				} catch (FileNotFoundException e) {
				}
			}
		}
		return in;
	}
	
	public static Path mkdirs(Path path) throws IOException {
		return Files.createDirectories(path);
	}
	/** 删除文件或目录 */
	public static void delete(File file) throws IOException {
		delete(file.toPath());
	}
	/** 删除文件或目录 */
	public static synchronized void delete(Path path) throws IOException {
		if (!Files.exists(path)) return;
		
		if (Files.isDirectory(path) && !Files.isSymbolicLink(path)) {
			for (Path child : path) {
				delete(child);
			}
		}
		Files.delete(path);
	}
	public static Path createTempDir(String prefix) throws IOException {
		return Files.createTempDirectory(prefix);
	}

	public static Properties loadProperties(String name) {
		Properties props = new Properties();
		try (InputStream in = UtilObj.getClassLoader().getResourceAsStream(name)) {
			if (in != null) props.load(in);
		} catch (IOException e) {
			throw new IllegalArgumentException(e);
		}
		return props;
	}
}
